/******************************************************************************
 *      Mestrado em Ciência da Computação - UFMS
 *		Redes de Computadores - Prof. Dr. Ronaldo Alves Ferreira
 *		Alunos: Geraldo Landre, Marcel Tolentino, Vinícius Bueno
 *****************************************************************************/

#include "cgibin.h"

/*****************************************************************
 * get_cgibin_folder_path -	retorna o caminho da raiz até
 *					a pasta do cgi-bin: ROOT_DIR + CGI_SUBPATH
 *					usar para comparação.
 *
 * parametros:
 *	**path:		parâmetro de retorno, será atribuído com a
 *					o caminho completo da pasta do cgibin
 *
 * retorno: length de **path.
 *****************************************************************/
int get_cgibin_folder_path(vstring *path)
{    
    copy_vstring(&path,configure.server_dir);
    concat_string(&path,CGI_SUBPATH);
    concat_string(&path,SLASH);
    
    return path->length;
}

/*****************************************************************
 * cgibin_exec -	tenta executar o programa passado pela url
 *					escreve a saída do programa em output
 *
 * parametros:
 *	*url:			url contendo o comando e os parâmetros a serem
 *					executados.
 *	**output:		parâmetro de retorno, será atribuído com a
 *					saída do programa
 *	**hd:			parâmetro de retorno, será atribuído com dados
 *					do cabeçalho
 *
 * retorno: length de *output;
 *****************************************************************/
int cgibin_exec(vstring *url,vstring *output,header_data **hd)
{
    vstring *cmd = NULL,*args = NULL,*aux = NULL;
    int replaces = 0;

    if((replaces = replace_all(&url,QUESTION,SPACE)) == 1)
    {
        get_token(&url,&cmd,SPACE);
        get_token(&url,&args,SPACE);

        if(cmd != NULL && args != NULL)
        {
            while(get_token(&args,&aux,AMPERSAND))
            {
                concat_string(&cmd,SPACE);
                concat_vstring(&cmd,aux);
            }
            // chama o programa
            call_program(cmd,output,hd);
        }
        else
        {
            (*hd)->error = ERR_BAD_REQUEST;
            copy_string(&output,"[cgibin_exec]: unrecognized parameters");
        }
    }
    else
        if(replaces == 0)
        {
            (*hd)->error = MSG_OK; // por enquanto tá tudo ok // TODO: tirar esta linha
            call_program(url,output,hd);
        }
        else
        {
            (*hd)->error = ERR_BAD_REQUEST;
	    copy_string(&output,"[cgibin_exec]: unrecognized URI");
        }

    return output->length;
} // cgibin_exec

/*****************************************************************
 * call_program -	executa o programa passado por parâmetro
 *					através da chamada de sistema popen()
 *
 * parametros:
 *	*command_line:	linha de comando do programa a ser executado
 *	**output:		parâmetro de retorno, será atribuído com a
 *					saída do programa
 *	**hd:			parâmetro de retorno, será atribuído com dados
 *					do cabeçalho
 *
 * retorno: length de *output se tudo der certo; -1 em caso de erro
 *****************************************************************/
int call_program(vstring *command,vstring *output,header_data **hd)
{
    vstring *line = NULL;
    FILE *fpipe = NULL;

    fpipe = (FILE*)popen(command->pt,"r");
    if(!fpipe)
    {
        (*hd)->error = ERR_NOT_FOUND;
        perror("error calling the program");
        copy_string(&output,"error calling the program");
    }
    else
    {
        alloc_string(&line,CGI_CALL_PROGRAM_BUFFER);
        // efetua a leitura do pipe do programa
        while(fgets(line->pt,CGI_CALL_PROGRAM_BUFFER,fpipe))
        {
            line->length = strlen(line->pt);
            concat_vstring(&output,line);
        }
        (*hd)->error = MSG_OK;

        // fecha o pipe do programa
        if(pclose(fpipe) == -1)
            perror("error closing fpipe");
    }
    return output->length;
} // call_program